package com.hexacta.hrs.web.struts.actions.feedbacks;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.SessionAware;
import org.vectrics.employee.Employee;
import org.vectrics.provider.CoreServiceLocator;
import org.vectrics.recruiter.RecruitServiceLocator;
import org.vectrics.recruiter.job.JobFunction;
import org.vectrics.user.Person;

import com.hexacta.hrs.domain.feedback.ArchivoAdjunto;
import com.hexacta.hrs.domain.feedback.FeedbackPeriod;
import com.hexacta.hrs.domain.feedback.Period;
import com.hexacta.hrs.securitygroups.PermissionName;
import com.hexacta.hrs.services.employee.EmployeeService;
import com.hexacta.hrs.services.feedbacks.FeedbackPeriodService;
import com.hexacta.hrs.services.feedbacks.PeriodService;
import com.hexacta.hrs.services.mentoring.MentoringService;
import com.hexacta.hrs.web.struts.actions.security.PermissionChecker;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

public class EmployeeFeedbackSummaryAction extends ActionSupport implements SessionAware, ServletRequestAware {

    /**
     * 
     */
    private static final long serialVersionUID = -637736393164256373L;

    private FeedbackPeriodService feedbackPeriodService;

    private PeriodService periodService;

    private EmployeeService employeeService;

    private MentoringService mentoringService;

    private PermissionChecker permissionChecker = new PermissionChecker();

    /* Defines */

    private String AUTOEVALUATION = "autoevaluation";

    private String DISCHARGE = "discharge";

    /* Parameters */

    private Long evaluatedId = null;

    private Long mentorId = null;

    private String roleCode = null;

    private String selectedEmployeeName;

    private Long prevEvaluatedId = (long) 0;

    private Long prevMentorId = (long) 0;

    private String prevRoleCode = "";

    private String periodId;

    private Period period;

    private HttpServletRequest request;

    /* Variables */

    private InputStream autoevaluationStream;

    private String fileName;

    private InputStream dischargeStream;

    private List<FeedbackPeriod> feedbackPeriods;

    private Map<String, Object> session;

    private String prevPeriodId;

    private Period prevPeriod;

    /* Actions */

    @Override
    public String execute() {
        return initFilters();
    }

    public String initFilters() {
        initParams();
        return SUCCESS;
    }

    public String filter() {
        setOldParams();
        if (evaluatedId == null && roleCode == null && mentorId == null) {
            feedbackPeriods = new ArrayList<FeedbackPeriod>();
            return SUCCESS;
        }
        filterPeriods();
        initParams();
        return SUCCESS;
    }

    // TODO: refactorear para que downloadDischarge y downloadAutoevaluation me
    // queden m�s parejitos. se pueden unir en un m�todo download.
    public String downloadDischarge() {
        Object feedbackId = ActionContext.getContext().getParameters().get("feedbackId");
        Long id = Long.valueOf(((String[]) feedbackId)[0]);
        FeedbackPeriod feedbackPeriod = feedbackPeriodService.findById(id);

        ArchivoAdjunto discharge = feedbackPeriod.getDischarge();

        if (discharge == null) {
            addFieldError("discharge", "Employee has no discharge for this period");
            resetParams();
            return filter();
        }

        dischargeStream = new ByteArrayInputStream(discharge.getBytes());
        fileName = discharge.getNombre();

        return DISCHARGE;
    }

    public String downloadAutoevaluation() {

        Object feedbackId = ActionContext.getContext().getParameters().get("feedbackId");
        Long id = Long.valueOf(((String[]) feedbackId)[0]);
        FeedbackPeriod feedbackPeriod = feedbackPeriodService.findById(id);

        ArchivoAdjunto autoevaluation = feedbackPeriod.getSelfevaluation();

        if (autoevaluation == null) {
            addFieldError("autoevaluation", "Employee has no self-evaluation for this period");
            resetParams();
            return filter();
        }

        autoevaluationStream = new ByteArrayInputStream(autoevaluation.getBytes());
        fileName = autoevaluation.getNombre();

        return AUTOEVALUATION;
    }

    /* Private methods */

    private void initParams() {

        if (StringUtils.isEmpty(periodId)) {
            try {
                period = periodService.getOpenPeriod();
                periodId = period.getYear();
            } catch (Exception e) {
                period = periodService.getLastPeriod();
                periodId = period.getYear();
            }

        } else {
            period = periodService.getPeriodByYear(periodId);
        }

        setEvaluatedId((long) 0);
        setMentorId((long) 0);
        setRoleCode("");
        setSelectedEmployeeName("");

    }

    /**
     * saves old parameters in order to restore them in case of error
     */
    private void setOldParams() {
        prevEvaluatedId = evaluatedId;
        prevMentorId = mentorId;
        prevRoleCode = roleCode;
        prevPeriodId = periodId;
        prevPeriod = period;
    }

    /**
     * resets parameters in case of error
     */
    private void resetParams() {
        evaluatedId = prevEvaluatedId;
        mentorId = prevMentorId;
        roleCode = prevRoleCode;
        periodId = prevPeriodId;
        period = prevPeriod;
    }

    private void filterPeriods() {

        Person person = CoreServiceLocator.getUserAuthService().getAuthorizedPerson(getSession());

        if (StringUtils.isEmpty(periodId)) {
            period = periodService.getOpenPeriod();
            if (period == null) {
                period = periodService.getLastPeriod();
            }
        } else {
            period = periodService.getPeriodByYear(periodId);
        }
        feedbackPeriods = (List<FeedbackPeriod>) feedbackPeriodService.findFeedbackPeriodsWithCriteria(period,
                person.getId(), evaluatedId, roleCode, mentorId);

    }

    /* Getters/Setters */

    /**
     * @return
     */
    private Map<String, Object> getSession() {
        return session;
    }

    /**
     * @return the evaluatedEmployees
     */
    public List<Employee> getEvaluatedEmployees() {
        // TODO: obtener los empleados seg�n reglas a especificar por Dami�n
        // Terenzi.
        return (List<Employee>) employeeService.getAllCurrentEmployees();
    }

    /**
     * @return the feedbacPeriodService
     */
    public FeedbackPeriodService getFeedbackPeriodService() {
        return feedbackPeriodService;
    }

    /**
     * @param feedbacPeriodService
     *            the feedbacPeriodService to set
     */
    public void setFeedbackPeriodService(final FeedbackPeriodService feedbackPeriodService) {
        this.feedbackPeriodService = feedbackPeriodService;
    }

    /**
     * @return the mentors
     */
    public List<Employee> getMentors() {
        // TODO: obtener los mentores para los empleados de la lista.
        return (List<Employee>) mentoringService.getAllActiveMentors();
    }

    /**
     * @return the roles
     */
    public List<JobFunction> getRoles() {
        // TODO: determinar si traemos todos los roles o s�lo aquellos menores
        // al usuario
        return RecruitServiceLocator.getJobProvider().findAllJobFunctions();
    }

    /**
     * @return the evaluatedId
     */
    public Long getEvaluatedId() {
        return evaluatedId;
    }

    /**
     * @param evaluatedId
     *            the evaluatedId to set
     */
    public void setEvaluatedId(final Long evaluatedId) {
        this.evaluatedId = evaluatedId;
    }

    /**
     * @return the mentorId
     */
    public Long getMentorId() {
        return mentorId;
    }

    /**
     * @param mentorId
     *            the mentorId to set
     */
    public void setMentorId(final Long mentorId) {
        this.mentorId = mentorId;
    }

    /**
     * @return the roleCode
     */
    public String getRoleCode() {
        return roleCode;
    }

    /**
     * @param roleCode
     *            the roleCode to set
     */
    public void setRoleCode(final String roleCode) {
        this.roleCode = roleCode;
    }

    /**
     * @return the selectedEmployeeName
     */
    public String getSelectedEmployeeName() {
        return selectedEmployeeName;
    }

    /**
     * @param selectedEmployeeName
     *            the selectedEmployeeName to set
     */
    public void setSelectedEmployeeName(final String selectedEmployeeName) {
        this.selectedEmployeeName = selectedEmployeeName;
    }

    /**
     * @return the employeeService
     */
    public EmployeeService getEmployeeService() {
        return employeeService;
    }

    /**
     * @param employeeService
     *            the employeeService to set
     */
    public void setEmployeeService(final EmployeeService employeeService) {
        this.employeeService = employeeService;
    }

    /**
     * @return los feedbacks que responden al filtro.
     */

    public List<FeedbackPeriod> getFeedbackPeriods() {
        return feedbackPeriods;
    }

    /**
     * @return the autoevaluationStream
     */
    public InputStream getAutoevaluationStream() {
        return autoevaluationStream;
    }

    public String getContentDisposition() {
        return "attachment;filename=" + fileName;
    }

    /**
     * @return the dischargeStream
     */
    public InputStream getDischargeStream() {
        return dischargeStream;
    }

    /**
     * @return the mentoringService
     */
    public MentoringService getMentoringService() {
        return mentoringService;
    }

    /**
     * @param mentoringService
     *            the mentoringService to set
     */
    public void setMentoringService(final MentoringService mentoringService) {
        this.mentoringService = mentoringService;
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.apache.struts2.interceptor.SessionAware#setSession(java.util.Map)
     */
    @Override
    public void setSession(final Map<String, Object> session) {
        this.session = session;

    }

    /**
     * @return the periodId
     */
    public String getPeriodId() {
        return periodId;
    }

    /**
     * @param periodId
     *            the periodId to set
     */
    public void setPeriodId(final String periodId) {
        this.periodId = periodId;
    }

    /**
     * @return the periodService
     */
    public PeriodService getPeriodService() {
        return periodService;
    }

    /**
     * @param periodService
     *            the periodService to set
     */
    public void setPeriodService(final PeriodService periodService) {
        this.periodService = periodService;
    }

    /**
     * @return the period
     */
    public Period getPeriod() {
        return period;
    }

    /**
     * @param period
     *            the period to set
     */
    public void setPeriod(final Period period) {
        this.period = period;
    }

    /**
     * @return the showReturn
     */
    public boolean isShowReturn() {
        String permission = PermissionName.MANAGE_FEEBACKS.toString();
        return permissionChecker.hasPermission(permission, request.getSession());
    }

    /**
     * @return the request
     */
    public HttpServletRequest getRequest() {
        return request;
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.apache.struts2.interceptor.ServletRequestAware#setServletRequest(
     * javax.servlet.http.HttpServletRequest)
     */
    @Override
    public void setServletRequest(final HttpServletRequest request) {
        this.request = request;
    }
}